#include <string.h>
#include <sqlite3.h>
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>

int contador = 0;
char* dbname = "rebides.db";
sqlite3 *db;
char buffer[600];
const int YEAR = 9;
int firstYear = 0;
int secondYear = 0;
int thirdYear = 0;
int fourthYear = 0;
int fifthYear = 0;
int sixthYear = 0;
int seventhYear = 0;
FILE* write;
char *zErrMsg = 0;
int firstStatisticSize;
int secondStatisticSize;
int thirdStatisticSize;
int thirdStatisticSize;
int fourthStatisticSize;
int firstListSize;
int secondListSize;
int thirdListSize;
int firstArrayPosition = 0;
int secondArrayPosition = 0;
int thirdArrayPosition = 0;
int fourthArrayPosition = 0;
int firstArrayListPosition = 0;
int secondArrayListPosition = 0;
int thirdArrayListPosition = 0;

//qsort Pointers
typedef int (*compfn)(const void*, const void*);


pthread_t pth ,pth2, pth3, pth4, pth5, pth6, pth7;


//Structs
struct NUMBEROFTEACHERSPERYEAR 
{
  int year;
  int totalTeachers;
};

struct TEACHERSPERESTABLISHMENT
{
  int year;
  int totalTeachers;
  char establishment[200];
};

struct TEACHERSPERDEGREE
{
  int year;
  int totalTeachers;
  char degree[200];
};

struct TEACHERSPERDEGREEPERESTABLISHMENT
{
  int year;
  int totalTeachers;
  char establishment[200];
  char degree[200];
};

struct LISTESTABLISHMENT
{
  int year;
  char establishment[200];
};


struct LISTINSTITUTE
{
  int year;
  char establishment[200];
};

struct HOLDERDEGREE
{
  int year;
  char name[200];
};


struct NUMBEROFTEACHERSPERYEAR *teachers;
struct TEACHERSPERESTABLISHMENT *teachersPerEstablishment;
struct TEACHERSPERDEGREE *teachersPerDegree;
struct TEACHERSPERDEGREEPERESTABLISHMENT *teachersPerDegreePerEstablishment;
struct LISTESTABLISHMENT *listEstablishment;
struct LISTINSTITUTE *listInstitute;
struct HOLDERDEGREE *listDegree;


//Sort Methods
int compareTotalTeachers(struct NUMBEROFTEACHERSPERYEAR *elem1, struct NUMBEROFTEACHERSPERYEAR *elem2)
{
  if ( elem1->totalTeachers > elem2->totalTeachers)
    return -1;

  else if (elem1->totalTeachers < elem2->totalTeachers)
    return 1;

  else
    return 0;
}

int compareTotalTeachersPerEstablishment(struct TEACHERSPERESTABLISHMENT *elem1, struct TEACHERSPERESTABLISHMENT *elem2)
{
  if ( elem1->totalTeachers > elem2->totalTeachers)
    return -1;

  else if (elem1->totalTeachers < elem2->totalTeachers)
    return 1;

  else
    return 0;
}

int compareTotalTeachersPerDegree(struct TEACHERSPERDEGREE *elem1, struct TEACHERSPERDEGREE *elem2)
{
  if ( elem1->totalTeachers > elem2->totalTeachers)
    return -1;

  else if (elem1->totalTeachers < elem2->totalTeachers)
    return 1;

  else
    return 0;
}

int compareTotalTeachersPerDegreePerEstablishment(struct TEACHERSPERDEGREEPERESTABLISHMENT *elem1, struct TEACHERSPERDEGREEPERESTABLISHMENT *elem2)
{
  if ( elem1->totalTeachers > elem2->totalTeachers)
    return -1;

  else if (elem1->totalTeachers < elem2->totalTeachers)
    return 1;

  else
    return 0;
}

//Sort Lists 

/* compare function for qsort */

int compareListEstablishment(struct LISTESTABLISHMENT *elem1, struct LISTESTABLISHMENT *elem2)
{
  if ( elem1->year > elem2->year)
    return -1;

  else if (elem1->year < elem2->year)
    return 1;

  else
    return 0;
}
 

int compareListInstitute(struct LISTINSTITUTE *elem1, struct LISTINSTITUTE *elem2)
{ 

  if ( elem1->year < elem2->year)
    return -1;

  else if (elem1->year > elem2->year)
    return 1;

  else
    return 0; 

}
int compareListHolderDegree(struct HOLDERDEGREE *elem1, struct HOLDERDEGREE *elem2)
{ 
  if ( elem1->name < elem2->name)
    return -1;

  else if (elem1->name > elem2->name)
    return 1;

  else
    return 0; 
}
//THREADS

void *threadFirstStatistic(void *arg)
{
  RecursiveTotalTeacher(YEAR);
  return NULL;
}

void *threadSecondStatistic(void *arg)
{
  RecursiveTotalTeacherPerEstablishment(YEAR);
  return NULL;
}

void *threadThirdStatistic(void *arg)
{
  RecursiveTotalTeacherPerDegree(YEAR);
  return NULL;
}


void *threadFourthStatistic(void *arg)
{
  RecursiveTotalTeacherPerDegreePerEstablishment(YEAR);
  return NULL;
}

void *threadFirstList(void *arg)
{
  RecursiveListEstablishment(YEAR);
  return NULL;
}

void *threadSecondList(void *arg)
{
  RecursiveListInstitute(YEAR);
  return NULL;
}

void *threadThirdList(void *arg)
{
  RecursiveListHolderDegree(YEAR);
  return NULL;
}


//Metodo Principal
int main(){

  write = fopen("Statistics_and_Lists.txt","w");
  sqlite3_open(dbname, &db);
  AllocMemory();

  pthread_create(&pth, NULL, threadFirstStatistic, "processing...");
  pthread_create(&pth2, NULL, threadSecondStatistic, "processing second statistic...");
  pthread_create(&pth3, NULL, threadThirdStatistic, "processing third statistic...");
  pthread_create(&pth4, NULL, threadFourthStatistic, "processing fourth statistic...");
  pthread_create(&pth5, NULL, threadFirstList, "processing first List");
  pthread_create(&pth6, NULL, threadSecondList, "processing sec List");
  pthread_create(&pth7, NULL, threadThirdList, "processing third List");

  pthread_join(pth, NULL);
  pthread_join(pth2, NULL);
  pthread_join(pth3, NULL);
  pthread_join(pth4, NULL);
  pthread_join(pth5, NULL);
  pthread_join(pth6, NULL);
  pthread_join(pth7, NULL);
 

  saveFile();

  //Fechar base de dados na gravaçao de ficheiro
  sqlite3_close(db);
  return 0;
}


//Database CallBacks

static int callbackTotalTeacher(void *NotUsed, int argc, char **argv, char **azColName){
  int i;
  for(i=0; i<argc; i++){
      teachers[firstArrayPosition].year = firstYear;
      teachers[firstArrayPosition].totalTeachers = atoi(argv[i]);
      firstArrayPosition++;
  }
  return 0;
}

static int callbackTotalTeacherForEstablishment(void *NotUsed, int argc, char **argv, char **azColName){
  int i;
  for(i=0; i<argc; i++){
    teachersPerEstablishment[secondArrayPosition].totalTeachers = atoi(argv[i]);
  }
  return 0;
}

static int callbackTotalTeacherPerEstablishment(void *NotUsed, int argc, char **argv, char **azColName){
  int i;
  char tmp[300];
  for(i=0; i<argc; i++){
    sprintf(tmp, "SELECT COUNT(DISTINCT docente) FROM fichas_docencia WHERE estabelecimento = '%s' and ano = (%d)", argv[i], secondYear);
    sqlite3_exec(db, tmp, callbackTotalTeacherForEstablishment, 0, &zErrMsg);
    teachersPerEstablishment[secondArrayPosition].year = secondYear;
    strcpy(teachersPerEstablishment[secondArrayPosition].establishment, argv[i]);
    secondArrayPosition++;
  }
  return 0;
}

static int callbackTotalTeacherForDegree(void *NotUsed, int argc, char **argv, char **azColName){
  int i;
  for(i=0; i<argc; i++){
    teachersPerDegree[thirdArrayPosition].totalTeachers = atoi(argv[i]);
  }
  return 0;
}

static int callbackTotalTeacherPerDegree(void *NotUsed, int argc, char **argv, char **azColName){
  int i;
  char tmp[500];
  for(i=0; i<argc; i++){
    sprintf(tmp, "SELECT COUNT(DISTINCT docente) FROM fichas_docencia WHERE grau = '%s' and ano = (%d)", argv[i], thirdYear);
    sqlite3_exec(db, tmp, callbackTotalTeacherForDegree, 0, &zErrMsg);
    teachersPerDegree[thirdArrayPosition].year = thirdYear;
    strcpy(teachersPerDegree[thirdArrayPosition].degree, argv[i]);
    thirdArrayPosition++;
  }
  return 0;
}


//CallBack Last Statistic

static int callbackForTotalTeacherPerDegreePerEstablishment(void *NotUsed, int argc, char **argv, char **azColName){
  int i;
  for(i=0; i<argc; i++){
	teachersPerDegreePerEstablishment[fourthArrayPosition].totalTeachers = atoi(argv[i]);
	fourthArrayPosition++;
	strcpy(teachersPerDegreePerEstablishment[fourthArrayPosition].establishment, teachersPerDegreePerEstablishment[fourthArrayPosition-1].establishment);
  }
  return 0;
}


static int callbackTotalTeacherPerDegreeForEstablishment(void *NotUsed, int argc, char **argv, char **azColName){
  int i;
  char tmp[700];
  char school[300];
  strcpy(school, teachersPerDegreePerEstablishment[fourthArrayPosition].establishment);
  for(i=0; i<argc; i++){
    strcpy(teachersPerDegreePerEstablishment[fourthArrayPosition].degree, argv[i]);
    sprintf(tmp, "SELECT COUNT(DISTINCT docente) FROM fichas_docencia WHERE grau = '%s' and ano = (%d) and estabelecimento = '%s'", argv[i], fourthYear, school);    
    sqlite3_exec(db, tmp, callbackForTotalTeacherPerDegreePerEstablishment, 0, &zErrMsg);
  }
  return 0;
}


static int callbackTotalTeacherPerDegreePerEstablisment(void *NotUsed, int argc, char **argv, char **azColName){
  int i;
  char tmp[700];
  for(i=0; i<argc; i++){
    teachersPerDegreePerEstablishment[fourthArrayPosition].year = fourthYear;
    strcpy(teachersPerDegreePerEstablishment[fourthArrayPosition].establishment, argv[i]);
    sprintf(tmp, "SELECT DISTINCT grau FROM fichas_docencia WHERE estabelecimento = '%s' and ano = (%d)", teachersPerDegreePerEstablishment[fourthArrayPosition].establishment, fourthYear);
    sqlite3_exec(db, tmp, callbackTotalTeacherPerDegreeForEstablishment, 0, &zErrMsg);
   }
  return 0;
}


//DATABASE CALLBACKS ALLOCATION

static int callbackTotalSizeAllocFirst(void *NotUsed, int argc, char **argv, char **azColName){
  int i;
  for(i=0; i<argc; i++){
    firstStatisticSize = atoi(argv[i]);
    teachers = (struct NUMBEROFTEACHERSPERYEAR*) malloc( sizeof(struct NUMBEROFTEACHERSPERYEAR) * firstStatisticSize);
  }
  return 0;
}

static int callbackTotalSizeAllocSecond(void *NotUsed, int argc, char **argv, char **azColName){
  int i;
  for(i=0; i<argc; i++){
    secondStatisticSize = atoi(argv[i])*YEAR;
    teachersPerEstablishment = (struct TEACHERSPERESTABLISHMENT*) malloc( sizeof(struct TEACHERSPERESTABLISHMENT) * (secondStatisticSize));
  }
  return 0;
}

static int callbackTotalSizeAllocThird(void *NotUsed, int argc, char **argv, char **azColName){
  int i;
  for(i=0; i<argc; i++){
    thirdStatisticSize = atoi(argv[i]) * YEAR;
    teachersPerDegree = (struct TEACHERSPERDEGREE*) malloc( sizeof(struct TEACHERSPERDEGREE) * (thirdStatisticSize));
  }
  return 0;
}



//// ALLOCATION  Methods

int AllocMemory(){
  //Alloc For First Statistic
  sprintf(buffer,"SELECT COUNT (DISTINCT ano) from fichas_docencia");
  sqlite3_exec(db, buffer, callbackTotalSizeAllocFirst, 0, &zErrMsg);
  //Alloc for second statistic
  sprintf(buffer,"SELECT COUNT (DISTINCT designacao) from estabelecimentos");
  sqlite3_exec(db, buffer, callbackTotalSizeAllocSecond, 0, &zErrMsg);
  //Alloc for third statistic
  sprintf(buffer,"SELECT COUNT (DISTINCT designacao) from graus");
  sqlite3_exec(db, buffer, callbackTotalSizeAllocThird, 0, &zErrMsg);
  //Alloc for fourth statistic
  allocEstablishmentDegree();
  //This method allocates memory for the first 3 Lists
  allocForLists();
  return 0;
}


//CALLBACK ALLOC LISTS


static int callbackAllocInstituteList(void *NotUsed, int argc, char **argv, char **azColName){
  int i;
  for(i=0; i<argc; i++){
    secondListSize = atoi(argv[i]) * YEAR;

    listInstitute = (struct LISTINSTITUTE*) malloc( sizeof(struct LISTINSTITUTE) * secondListSize);
  }
  return 0;
}

static int callbackAllocHolderList(void *NotUsed, int argc, char **argv, char **azColName){
  int i;
  for(i=0; i<argc; i++){
    thirdListSize = atoi(argv[i]) * YEAR;
    listDegree = (struct HOLDERDEGREE*) malloc( sizeof(struct HOLDERDEGREE) * thirdListSize);
  }
  return 0;
}


//More Allocs
int allocForLists(){
  firstListSize = secondStatisticSize;

  listEstablishment = (struct LISTESTABLISHMENT*) malloc( sizeof(struct LISTESTABLISHMENT) * firstListSize);
  strcpy(buffer,"SELECT COUNT (DISTINCT tipo_estabelecimento) from fichas_docencia");

  sqlite3_exec(db, buffer, callbackAllocInstituteList, 0, &zErrMsg);
  strcpy(buffer,"SELECT COUNT (DISTINCT docente) from fichas_docencia WHERE grau = 'Licenciatura'");
  sqlite3_exec(db, buffer, callbackAllocHolderList, 0, &zErrMsg); 
  return 0;
}

int allocEstablishmentDegree(){
  fourthStatisticSize = (thirdStatisticSize + secondStatisticSize) * 4;
  teachersPerDegreePerEstablishment = (struct TEACHERSPERDEGREEPERESTABLISHMENT*) malloc( sizeof(struct TEACHERSPERDEGREEPERESTABLISHMENT) * fourthStatisticSize);
  if(teachersPerDegreePerEstablishment != NULL)
    {
      //Alloc Not sucessed
      //Free memory and try alloc again
    }
  return 0;
}

//Program Methods

int RecursiveTotalTeacher(int year){
  if (year >= 0){
    char tmp[150];
    firstYear = year;
    sprintf(tmp,"SELECT COUNT (DISTINCT docente) from fichas_docencia WHERE ano = %d",year);
    sqlite3_exec(db, tmp, callbackTotalTeacher, 0, &zErrMsg);
    return RecursiveTotalTeacher(year-1);
  }
  int i;
  firstArrayPosition = 0;
  //Chamar Metodo para organizar informaçao QSORT
  qsort(teachers, firstStatisticSize, sizeof(struct NUMBEROFTEACHERSPERYEAR), (compfn)compareTotalTeachers);
  return 0;
}

int RecursiveTotalTeacherPerEstablishment(int year){
  if (year >= 0){
    char tmp[150];
    secondYear = year;
    sprintf(tmp,"SELECT DISTINCT estabelecimento FROM fichas_docencia WHERE ano = %d",year);
    sqlite3_exec(db, tmp, callbackTotalTeacherPerEstablishment, 0, &zErrMsg);
    return RecursiveTotalTeacherPerEstablishment(year-1);
  }
  secondArrayPosition = 0;
  
  //Chamar Metodo para organizar informaçao QSORT
  qsort(teachersPerEstablishment, secondStatisticSize, sizeof(struct TEACHERSPERESTABLISHMENT), (compfn)compareTotalTeachersPerEstablishment);

 return 0;
}


int RecursiveTotalTeacherPerDegree(int year){
  if (year >= 0){
    char tmp[200];
    thirdYear = year;
    sprintf(tmp,"SELECT DISTINCT grau FROM fichas_docencia WHERE ano = %d",year);
    sqlite3_exec(db, tmp, callbackTotalTeacherPerDegree, 0, &zErrMsg);
    return RecursiveTotalTeacherPerDegree(year-1);
  }
  thirdArrayPosition = 0;
  //Chamar Metodo para organizar informaçao QSORT
  qsort(teachersPerDegree, thirdStatisticSize, sizeof(struct TEACHERSPERDEGREE), (compfn)compareTotalTeachersPerDegree);

  return 0;
}

int RecursiveTotalTeacherPerDegreePerEstablishment(int year){
  if (year >= 0){
    char tmp[200];
    fourthYear = year;
    sprintf(tmp,"SELECT DISTINCT estabelecimento FROM fichas_docencia WHERE ano = %d",year);
    sqlite3_exec(db, tmp, callbackTotalTeacherPerDegreePerEstablisment, 0, &zErrMsg);
    return RecursiveTotalTeacherPerDegreePerEstablishment(year-1);
  }
  fourthArrayPosition = 0;
  //Chamar Metodo para organizar informaçao QSORT                                                                                                                     
  qsort(teachersPerDegreePerEstablishment, fourthStatisticSize, sizeof(struct TEACHERSPERDEGREEPERESTABLISHMENT), (compfn)compareTotalTeachersPerDegreePerEstablishment);

  return 0;
}

//LISTS CALLBACKS

static int callbackListEstablishment(void *NotUsed, int argc, char **argv, char **azColName){
  int i;
  for(i=0; i<argc; i++){
    listEstablishment[firstArrayListPosition].year = fifthYear;
    strcpy(listEstablishment[firstArrayListPosition].establishment, argv[i]);
    firstArrayListPosition++;
   }
  return 0;
}

static int callbackListInstitute(void *NotUsed, int argc, char **argv, char **azColName){
  int i;
  for(i=0; i<argc; i++){
    listInstitute[secondArrayListPosition].year = sixthYear;
    strcpy(listInstitute[secondArrayListPosition].establishment, argv[i]);

    printf("nome arg = %s\n", argv[i]);
    printf("nome inst = %s\n", listInstitute[secondArrayListPosition].establishment);
    secondArrayListPosition++;
   }
  return 0;
}

static int callbackListHolderDegree(void *NotUsed, int argc, char **argv, char **azColName){
  int i;
  for(i=0; i<argc; i++){
    listDegree[thirdArrayListPosition].year = seventhYear;
    strcpy(listDegree[thirdArrayListPosition].name, argv[i]);
    thirdArrayListPosition++;
   }
  return 0;
}


//LISTS METHODS

int RecursiveListEstablishment(int year){
  if (year >= 0){
    char tmp[200];
    fifthYear = year;
    sprintf(tmp,"SELECT DISTINCT estabelecimento FROM fichas_docencia WHERE ano = %d",year);
    sqlite3_exec(db, tmp, callbackListEstablishment, 0, &zErrMsg);
    return RecursiveListEstablishment(year-1);
  }
  firstArrayListPosition = 0;
  //Chamar Metodo para organizar informaçao QSORT                                                                                                                     
  qsort(listEstablishment, firstListSize, sizeof(struct LISTESTABLISHMENT), (compfn)compareListEstablishment);
  return 0;
}

int RecursiveListInstitute(int year){
  if (year >= 0){
    char tmp[200];
    sixthYear = year;
    sprintf(tmp,"SELECT DISTINCT tipo_estabelecimento FROM fichas_docencia WHERE ano = %d",year);
    sqlite3_exec(db, tmp, callbackListInstitute, 0, &zErrMsg);
    return RecursiveListInstitute(year-1);
  }
  int i;
  for(i=secondArrayListPosition; i < secondListSize; i++){
    strcpy(listInstitute[i].establishment, "\0");
    listInstitute[i].year = NULL;
  }
  secondArrayListPosition = 0;
  //Chamar Metodo para organizar informaçao QSORT                                                                                                                     
  qsort(listInstitute, secondListSize, sizeof(struct LISTINSTITUTE), (compfn)compareListInstitute);

  return 0;
}

int RecursiveListHolderDegree(int year){
  if (year >= 0){
    char tmp[200];
    seventhYear = year;
    sprintf(tmp,"SELECT DISTINCT docente FROM fichas_docencia WHERE ano = %d and grau = 'Licenciatura'",year);
    sqlite3_exec(db, tmp, callbackListHolderDegree, 0, &zErrMsg);
    return RecursiveListHolderDegree(year-1);
  }
  thirdArrayListPosition = 0;
  //Chamar Metodo para organizar informaçao QSORT                                                                                                                     
  qsort(listDegree, thirdListSize, sizeof(struct LISTINSTITUTE), (compfn)compareListHolderDegree);

  return 0;
}



//File Save

int saveListEstablishment(){
  //Por no Ficheiro
  int i = 0;
  char bufferWriter [250];
  char newLine[2] = "\n";
  fputs("List Establishments Per Year \n\n",write);

  do{
    sprintf(bufferWriter, "Year 200%d ", listEstablishment[i].year);
    fputs(bufferWriter,write);
    fputs(listEstablishment[i].establishment,write);
    fputs(newLine, write);
    i++;
  }while(listEstablishment[i].establishment[0] != '\0');
  //Free Memory
  free (listEstablishment);
  return 0;
}

int saveListInstitute(){
  //Por no Ficheiro
  int i = 0;
  char bufferWriter [250];
  fputs("\n\nList Institutes Per Year \n\n",write);
  printf("Nome do instituto %s \n",listInstitute[0].establishment);
  do{
      sprintf(bufferWriter, "Year 200%d ", listInstitute[i].year);
      fputs(bufferWriter,write);
      fputs(listInstitute[i].establishment,write); 
      fputs("\n",write);
      i++;
  }while(listInstitute[i].establishment[0] != '\0');
  //Free Memory
  free (listInstitute);
  return 0;
}


int saveListHolder(){
  //Por no Ficheiro
  int i = 0;
  char bufferWriter [180];
  fputs("\n\nList Holders of Degree Per Year \n\n",write);
  do{
    sprintf(bufferWriter, "Year 200%d ", listDegree[i].year);
    fputs(bufferWriter,write);
    fputs(listDegree[i].name,write); 
    fputs("\n",write);
    i++;
  }while(listDegree[i].name[0] != '\0');

  //Free Memory
  free (listDegree);
  return 0;
}


int saveTotalTeachers(){
  //Por no Ficheiro
  int i = 0;
  char bufferWriter [500];
  fputs("Number of Teacher Per Year \n\n",write);
  for(i=0; i<firstStatisticSize; i++){
    sprintf(bufferWriter, "Year 200%d ", teachers[i].year);
    fputs(bufferWriter,write);
    sprintf(bufferWriter, "Total of Teachers = %d \n", teachers[i].totalTeachers);
    fputs(bufferWriter,write); 
  }
  //Free Memory
  free (teachers);
 
  return 0;
}

int saveTotalTeachersPerEstablishment(){
  //Gravar para o ficheiro
  int i = 0;
  char writeBuffer [600];
  fputs("\n\n\nNumber of Teacher Per Establishment \n\n",write);
  for(i=0; i<secondStatisticSize; i++){
    if(teachersPerEstablishment[i].totalTeachers == 0)
      continue;
    sprintf(writeBuffer, "Year 200%d ", teachersPerEstablishment[i].year);
    fputs(writeBuffer,write);
    sprintf(writeBuffer, "Establishment Name: %s ", teachersPerEstablishment[i].establishment);
    fputs(writeBuffer,write);
    sprintf(writeBuffer, "Total of Teachers = %d \n", teachersPerEstablishment[i].totalTeachers);
    fputs(writeBuffer,write);
  }

  free (teachersPerEstablishment);
   
  return 0;
}

int saveTotalTeachersPerDegree(){
  //Gravar para o ficheiro                                                                                                                                             
  int i = 0;
  char writeBuffer [600];
  fputs("\n\n\nNumber of Teacher Per Degree \n\n",write);
  for(i=0; i<thirdStatisticSize; i++){
    if(teachersPerDegree[i].totalTeachers == 0)
      continue;
    sprintf(writeBuffer, "Year 200%d ", teachersPerDegree[i].year);
    fputs(writeBuffer,write);
    sprintf(writeBuffer, "Degree: %s ", teachersPerDegree[i].degree);
    fputs(writeBuffer,write);
    sprintf(writeBuffer, "Total of Teachers = %d \n", teachersPerDegree[i].totalTeachers);
    fputs(writeBuffer,write);
  }

  free (teachersPerDegree);
  return 0;
}

int saveTotalTeachersPerDegreePerEstablishment(){
  //Gravar para o ficheiro                                                                                                                                             
  int i = 0;
  char writeBuffer [700];
  fputs("\n\n\nNumber of Teacher Per Degree Per Establishment\n\n",write);
 
    // if(teachersPerDegreePerEstablishment[i].establishment == teachersPerDegreePerEstablishment[i++].establishment && ){

 do{   
      sprintf(writeBuffer, "Year 200%d ", teachersPerDegreePerEstablishment[i].year);
      fputs(writeBuffer,write);
      sprintf(writeBuffer, "Establishment: %s \n ", teachersPerDegreePerEstablishment[i].establishment);
      fputs(writeBuffer,write);
      sprintf(writeBuffer, "Degree: %s ", teachersPerDegreePerEstablishment[i].degree);
      fputs(writeBuffer,write);
      sprintf(writeBuffer, "Total of Teachers = %d \n", teachersPerDegreePerEstablishment[i].totalTeachers);
      fputs(writeBuffer,write);
      i++;
 }while(teachersPerDegreePerEstablishment[i].totalTeachers != NULL);
  free (teachersPerDegreePerEstablishment);

  return 0;
}

int saveFile(){
  saveTotalTeachers();
  saveTotalTeachersPerEstablishment();
  saveTotalTeachersPerDegree();
  saveTotalTeachersPerDegreePerEstablishment();
  saveListEstablishment();
  saveListInstitute();
  saveListHolder();
  return 0;
}
